package com.heima.comment.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.comment.dtos.CommentRepayDto;
import com.heima.comment.dtos.CommentRepayLikeDto;
import com.heima.comment.dtos.CommentRepayListDto;
import com.heima.comment.pojos.ApComment;
import com.heima.comment.pojos.ApCommentLike;
import com.heima.comment.service.CommentRepayService;
import com.heima.comment.vos.ApCommentVo;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.feign.client.ApUserFeignClient;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojos.ApUser;
import com.heima.utils.thread.ApThreadLocal;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.core.query.UpdateDefinition;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class CommentRepayServiceImpl implements CommentRepayService {


    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private ApUserFeignClient apUserFeignClient;


    @Autowired
    private GreenTextScan greenTextScan;

    /**
     * 查询评论回复列表
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult loadCommentRepay(CommentRepayListDto dto) {
        //1.检查参数
        if (dto.getCommentId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        if (dto.getSize() == null || dto.getSize() == 0) {
            dto.setSize(10);
        }
        dto.setSize(Math.min(dto.getSize(), 50));

        //2根据文章id去查询mongo的评论表，并进行分页和排序展示
        Query query = Query.query(Criteria.where("targetId").is(dto.getCommentId()).and("createdTime")
                        .lt(dto.getMinDate()))
                .with(Sort.by(Sort.Direction.DESC, "createdTime")) //排序
                .limit(dto.getSize()); //分页
        List<ApComment> commentList = mongoTemplate.find(query, ApComment.class);
        if (commentList == null && commentList.size() == 0) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "没有查询到信息");
        }
        //3.如果此刻是游客登录的话，则直接返回评论列表
        ApUser user = ApThreadLocal.getApUser();
        if (user.getId() == 0) {
            return ResponseResult.okResult(commentList);
        }
        //4.否则就是用户登录，加载数据的时候，要判断当前用户点赞了拿些评论，并给予标识
        //4.1 查询redis中是否有点赞数据
        String key = "COMMENT_REPAY_LIKE_" + user.getId();
        //根据key查询出所有的值
        Set<String> like_ids = stringRedisTemplate.opsForSet().members(key);
        //4.2 如果没有查询到数据,则直接返回评论列表
        if (like_ids == null|| like_ids.size()==0) {
            return ResponseResult.okResult(commentList);
        }
        //4.3 否则，就是存在点赞数据，则添加标记
        List<ApCommentVo> resultList = commentList.stream().map(comment -> {
            ApCommentVo vo = new ApCommentVo();
            BeanUtils.copyProperties(comment, vo);
            if (like_ids.contains(comment.getId())) {
                vo.setOperation((short) 0);
            }
            return vo;

        }).collect(Collectors.toList());
        //5. 返回数据

        return ResponseResult.okResult(resultList);
    }


    /**
     * 发送评论回复
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult saveCommentRepay(CommentRepayDto dto) {
        //1.检查参数
        if (dto.getCommentId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE, "文章id为空");
        }
        if (dto.getContent() != null && dto.getContent().length() > 140) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE, "评论内容不能超过140字");
        }

        //1.5对文章内容进行垃圾检测
        boolean textFlag = this.textScan(dto.getContent());
        if (!textFlag) {
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR, "含有敏感词，重新编写");
        }
        //2.判断是否登录
        ApUser apUser = ApThreadLocal.getApUser();
        //2.5 判断如果是游客身份则不允许发表评论
        if (apUser == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN, "用户信息为空，登录后操作");
        }
        //2.5 判断如果是游客身份则不允许发表评论
        if (apUser.getId() == 0) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN, "请登录之后再来评论！！");

        }
        //3.查询用户信息------先从redis中查询，如果不存在再从用户微服务中去查询
        String userKey = "LOGIN_USER_" + apUser.getId();//从redis中缓存
        String userStr = stringRedisTemplate.opsForValue().get(userKey);
        String parse =String.valueOf(JSON.parse(userStr));


        //4.如果存在就直接使用redis中的信息
        if (userStr != null) {
            apUser = JSON.parseObject(parse, ApUser.class);
        } else {
            //5.不存在就远程调用feign来 报存一分到redis中
            ResponseResult<ApUser> responseResult = apUserFeignClient.findUserById(apUser.getId());
            if (responseResult.getCode() == 200) {//拿到数据
                apUser = responseResult.getData();
                //报存daoredis中
                stringRedisTemplate.opsForValue().set(userKey, JSON.toJSONString(apUser));
            }
        }
        //6.报存到mongo中
        ApComment apComment = new ApComment();
        apComment.setContent(dto.getContent());
        apComment.setCreatedTime(new Date());
        apComment.setImage(apUser.getImage());
        apComment.setLikes(0);
        apComment.setUserId(apUser.getId());
        apComment.setReply(0);
        apComment.setNickName(apUser.getName());
        mongoTemplate.save(apComment);
        apComment.setUpdatedTime(new Date());
        apComment.setTargetId(dto.getCommentId());

        return ResponseResult.okResult("发布评论成功");
    }
    /**
     * 抽取审核垃圾检测文本的方法
     *
     * @param
     * @param content
     * @return
     */
    private boolean textScan(String content) {

        boolean flag = true;

        try {
            Map scanTextMap = greenTextScan.greeTextScan(content);
            //违规，审核不通过
            if (scanTextMap.get("suggestion").equals("block")) {
                //修改wm_news表的状态
                flag = false;
            }
            //表示需要人工审核
            if (scanTextMap.get("suggestion").equals("review")) {
                //修改wm_news表的状态
                flag = false;
            }

        } catch (Exception e) {
            e.printStackTrace();
            flag = false;
        }
        return flag;
    }

    /**
     * 点赞评论回复
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult saveCommentRepayLike(CommentRepayLikeDto dto) {
        //1.检查参数
        if (dto.getCommentRepayId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        //2.判断是否登录
        ApUser apUser = ApThreadLocal.getApUser();
        if (apUser == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //2.5 判断如果是游客身份则不允许发表评论
        if (apUser.getId() == 0) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN, "请登录之后再来点赞！！");
        }

        //判断当前评论信息是否存在，如果不存在，直接返回
        ApComment apComment = mongoTemplate.findById(dto.getCommentRepayId(), ApComment.class);
        if (apComment == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }


        //3.查询redis,是否有点赞过
        //定义key
        String comment_likes_key = "COMMENT_REPAY_LIKE_" + apUser.getId();
        //表示根据当前key下的所有的value中是否包含某一个，如果包含返回true,否则false
        Boolean memberFlag = stringRedisTemplate.opsForSet().isMember(comment_likes_key, dto.getCommentRepayId());

        //4 如果点赞过，并且现在正在执行的是点赞操作，直接返回
        if (memberFlag && dto.getOperation() == 0) {
            return ResponseResult.okResult(AppHttpCodeEnum.DATA_EXIST);
        }
        //5  如果点赞过，并且正在执行的是取消点赞，删除redis,删除mongo中点赞集合，修改mongo中的评论集合，点赞数-1
        if (memberFlag && dto.getOperation() == 1) {
            //删除redis
            stringRedisTemplate.opsForSet().remove(comment_likes_key, dto.getCommentRepayId());
            //删除mongo中点赞集合
            mongoTemplate.remove(Query.query(Criteria.where("userId").is(apUser.getId()).and("targetId").is(dto.getCommentRepayId())), ApCommentLike.class);

            //修改mongo中的评论集合，点赞数-1
            Query query = Query.query(Criteria.where("id").is(apComment.getId()).and("likes").gt(0));
            UpdateDefinition update = new Update().inc("likes", -1);
            mongoTemplate.updateFirst(query, update, ApComment.class);
        }
        //6 如果没有点赞过，并且正在执行的是点赞操作，新增redis,新增mongo中的点赞集合，修改mongo中的评论集合，点赞数+1
        if (!memberFlag && dto.getOperation() == 0) {
            //新增redis
            stringRedisTemplate.opsForSet().add(comment_likes_key, dto.getCommentRepayId());
            //新增mongo中的点赞集合
            ApCommentLike apCommentLike = new ApCommentLike();
            apCommentLike.setId(ObjectId.get().toHexString());
            apCommentLike.setTargetId(dto.getCommentRepayId());
            apCommentLike.setCreatedTime(new Date());
            apCommentLike.setUserId(apUser.getId());
            mongoTemplate.insert(apCommentLike);
            //修改mongo中的评论集合，点赞数+1
            Query query = Query.query(Criteria.where("id").is(apComment.getId()));
            UpdateDefinition update = new Update().inc("likes", 1);
            mongoTemplate.updateFirst(query, update, ApComment.class);
        }
        //4.返回数据
        apComment = mongoTemplate.findById(dto.getCommentRepayId(), ApComment.class);

        Map map = new HashMap();
        map.put("likes", apComment.getLikes());

        return ResponseResult.okResult(map);
    }
}
